package com.coldworks.base.manager;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.params.HttpClientParams;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.coldworks.base.util.BaseCONST;
import com.coldworks.coldjoke.R;

import android.content.Context;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.text.TextUtils;
import android.widget.Toast;

/**
 * 本地网络管理器
 * 
 * @since 2012-07-07
 */
public class BaseNetworkManager {
	protected final Logger log = LoggerFactory.getLogger(this.getClass());
	private static BaseNetworkManager instance = null;

	private BaseNetworkManager() {
	}

	public static BaseNetworkManager getInstance() {
		if (instance == null) {
			synchronized (BaseNetworkManager.class) {
				if (instance == null) {
					instance = new BaseNetworkManager();
				}
			}
		}
		return instance;
	}

	/**
	 * 检查网络 如果网络正常则正常显示 否则让用户选择去管理页还是去系统设置页
	 */
	public void checkNetwork(Context context) {
		if (BaseNetworkManager.getInstance().isNetworkAvailable(context)) {
			log.info("available");
			return;
		}
		log.warn("unavailable");
		Toast.makeText(context, context.getString(R.string.err_network),
				Toast.LENGTH_LONG).show();
	}

	/**
	 * 网络类型： 0.无网络 1.wifi 2.net网络 3.移动wap 4.联通wap 4.电信wap 5.未知网络
	 **/
	public String getNetworkType(Context context) {
		try {
			ConnectivityManager connect = (ConnectivityManager) context
					.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo actNetInfo = connect.getActiveNetworkInfo();
			if (actNetInfo == null) {
				log.warn("networkinfo: null");
				return BaseCONST.NETWORK.DISABLED;
			}
			if (!actNetInfo.isAvailable()) {
				log.info("type: disabled");
				return BaseCONST.NETWORK.DISABLED;
			}
			int netType = actNetInfo.getType();
			if (netType == ConnectivityManager.TYPE_WIFI) {
				log.info("type: wifi");
				return BaseCONST.NETWORK.WIFI;
			}
			if (netType != ConnectivityManager.TYPE_MOBILE) {
				log.warn("type: other(" + netType + ")");
				return BaseCONST.NETWORK.OTHER;
			}
			Cursor cursor = context.getContentResolver().query(
					BaseCONST.API.URI_PREFERAPN, null, null, null, null);
			if (cursor != null) {
				cursor.moveToFirst();
				String user = cursor.getString(cursor.getColumnIndex("user"));
				if (!TextUtils.isEmpty(user)) {
					String proxy = cursor.getString(cursor
							.getColumnIndex("proxy"));
					log.info("proxy: " + proxy + " user: " + user);
					if (user.startsWith("ctwap")) {
						log.info("type: CTWAP");
						return BaseCONST.NETWORK.CTWAP;
					}
				}
			}
			cursor.close();
			String extrainfo = actNetInfo.getExtraInfo();
			if (extrainfo != null) {
				extrainfo = extrainfo.toLowerCase();
				// 3gnet/3gwap/uninet/uniwap/cmnet/cmwap/ctnet/ctwap
				log.info("extrainfo: " + extrainfo);
				if (extrainfo.equals("cmwap")) {
					log.info("type: CMWAP");
					return BaseCONST.NETWORK.CMWAP;
				}
				if (extrainfo.equals("uniwap")) {
					log.info("type: UNIWAP");
					return BaseCONST.NETWORK.UNIWAP;
				}
			}
			log.info("type: NET");
			return BaseCONST.NETWORK.MOBILE;
		} catch (Exception e) {
			log.error("", e);
			log.warn("type: other");
			return BaseCONST.NETWORK.OTHER;
		}
	}

	/**
	 * 是否有可用网络
	 * 
	 * @param context
	 * @return
	 */
	public boolean isNetworkAvailable(Context context) {
		return isWifiConnected(context) || isMobileConnected(context);
	}

	/**
	 * WIFI是否连接
	 * 
	 * @param context
	 * @return
	 */
	public boolean isWifiConnected(Context context) {
		try {
			ConnectivityManager connectivityManager = (ConnectivityManager) context
					.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo wifi = connectivityManager
					.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
			if (wifi != null && wifi.isConnected()) {
				return true;
			}
		} catch (Exception e) {
			log.error("", e);
		}
		return false;
	}

	/**
	 * 2G/3G是否连接
	 * 
	 * @param context
	 * @return
	 */
	public boolean isMobileConnected(Context context) {
		try {
			ConnectivityManager connectivityManager = (ConnectivityManager) context
					.getSystemService(Context.CONNECTIVITY_SERVICE);
			NetworkInfo mobile = connectivityManager
					.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
			if (mobile != null && mobile.isConnected()) {
				return true;
			}
		} catch (Exception e) {
			log.error("", e);
		}
		return false;
	}

	public String httpGET(Context context, String fullURL) {
		URI u;
		try {
			URL sUrl = new URL(fullURL);
			u = sUrl.toURI();
		} catch (MalformedURLException e) {
			log.error("", e);
			return null;
		} catch (URISyntaxException e) {
			log.error("", e);
			return null;
		}
		HttpClient httpClient = createHttpClient(context);
		InputStream is = null;
		try {
			HttpGet httpGet = new HttpGet(u);
			httpGet.setHeader("Accept", "application/json");
			HttpResponse response = httpClient.execute(httpGet);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				throw new IOException("statusCode=" + statusCode);
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				is = entity.getContent();
				return readStream(is);
			}
		} catch (OutOfMemoryError e) {
			System.gc();
			log.error("", e);
		} catch (ClientProtocolException e) {
			log.error("", e);
		} catch (IOException e) {
			log.error("", e);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					log.error("", e);
				}
			}
			httpClient.getConnectionManager().shutdown();
			httpClient = null;
		}
		return null;
	}

	public HttpEntity httpGETEntity(Context context, String fullURL) {
		URI u;
		try {
			URL sUrl = new URL(fullURL);
			u = sUrl.toURI();
		} catch (MalformedURLException e) {
			log.error("", e);
			return null;
		} catch (URISyntaxException e) {
			log.error("", e);
			return null;
		}
		HttpClient httpClient = createHttpClient(context);
		try {
			HttpGet httpGet = new HttpGet(u);
			httpGet.setHeader("Accept", "application/json");
			HttpResponse response = httpClient.execute(httpGet);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				throw new IOException("statusCode=" + statusCode);
			}
			return response.getEntity();
		} catch (OutOfMemoryError e) {
			System.gc();
			log.error("", e);
		} catch (ClientProtocolException e) {
			log.error("", e);
		} catch (IOException e) {
			log.error("", e);
		} finally {
			// httpClient.getConnectionManager().shutdown();
			// httpClient = null;
		}
		return null;
	}

	public HttpResponse httpGETResponse(Context context, String fullURL) {
		URI u;
		try {
			URL sUrl = new URL(fullURL);
			u = sUrl.toURI();
		} catch (MalformedURLException e) {
			log.error("", e);
			return null;
		} catch (URISyntaxException e) {
			log.error("", e);
			return null;
		}
		HttpClient httpClient = createHttpClient(context);
		try {
			HttpGet httpGet = new HttpGet(u);
			httpGet.setHeader("Accept", "application/json");
			return httpClient.execute(httpGet);
		} catch (OutOfMemoryError e) {
			System.gc();
			log.error("", e);
		} catch (ClientProtocolException e) {
			log.error("", e);
		} catch (IOException e) {
			log.error("", e);
		} finally {
			// httpClient.getConnectionManager().shutdown();
			// httpClient = null;
		}
		return null;
	}

	public byte[] httpGet(Context context, String fullURL) {
		URI u;
		try {
			URL sUrl = new URL(fullURL);
			u = sUrl.toURI();
		} catch (MalformedURLException e) {
			log.error("", e);
			return null;
		} catch (URISyntaxException e) {
			log.error("", e);
			return null;
		}
		HttpClient httpClient = createHttpClient(context);
		InputStream is = null;
		ByteArrayOutputStream baos = null;
		try {
			HttpGet httpGet = new HttpGet(u);
			httpGet.setHeader("Accept", "application/json");
			HttpResponse response = httpClient.execute(httpGet);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				throw new IOException("statusCode=" + statusCode);
			}
			HttpEntity entity = response.getEntity();
			long size = entity.getContentLength();
			is = entity.getContent();
			if (is != null && size > 0) {
				baos = new ByteArrayOutputStream();
				byte[] buf = new byte[BaseCONST.HTTP.BUFFER_SIZE];
				int ch = -1;
				long count = 0;
				while ((ch = is.read(buf)) != -1) {
					count += ch;
					baos.write(buf, 0, ch);
				}
				baos.flush();
				if (count == size) {
					return baos.toByteArray();
				} else {
					return null;
				}
			}
		} catch (OutOfMemoryError e) {
			System.gc();
			log.error("", e);
		} catch (ClientProtocolException e) {
			log.error("", e);
		} catch (IOException e) {
			log.error("", e);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					log.error("", e);
				}
			}
			if (baos != null) {
				try {
					baos.close();
				} catch (IOException e) {
					log.error("", e);
				}
			}
			httpClient.getConnectionManager().shutdown();
			httpClient = null;
		}
		return null;
	}

	public String httpPOST(Context context, String fullURL,
			Map<String, String> paramsMap) {
		URI u;
		try {
			URL sUrl = new URL(fullURL);
			u = sUrl.toURI();
		} catch (MalformedURLException e) {
			log.error("", e);
			return null;
		} catch (URISyntaxException e) {
			log.error("", e);
			return null;
		}
		HttpClient httpClient = createHttpClient(context);
		InputStream is = null;
		try {
			HttpPost httpPost = new HttpPost(u);
			httpPost.setHeader("Accept", "application/json");
			List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>();
			for (Map.Entry<String, String> map : paramsMap.entrySet()) {
				nameValuePairs.add(new BasicNameValuePair(map.getKey(), map
						.getValue()));
			}

			httpPost.setEntity(new UrlEncodedFormEntity(nameValuePairs));
			HttpResponse response = httpClient.execute(httpPost);
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode != HttpStatus.SC_OK) {
				throw new IOException("statusCode=" + statusCode);
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				is = entity.getContent();
				Header contentEncoding = response
						.getFirstHeader("Content-Encoding");
				if (contentEncoding != null
						&& contentEncoding.getValue().equalsIgnoreCase("gzip")) {
					return readStream(is);
				} else {
					return readStream(is);
				}
			}
		} catch (OutOfMemoryError e) {
			System.gc();
			log.error("", e);
		} catch (ClientProtocolException e) {
			log.error("", e);
		} catch (IOException e) {
			log.error("", e);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					log.error("", e);
				}
			}
			httpClient.getConnectionManager().shutdown();
			httpClient = null;
		}
		return null;
	}

	public DefaultHttpClient createHttpClient(Context context) {
		HttpParams httpParams = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(httpParams,
				BaseCONST.HTTP.CONNECT_TIMEOUT);
		HttpConnectionParams
				.setSoTimeout(httpParams, BaseCONST.HTTP.SO_TIMEOUT);
		HttpConnectionParams.setSocketBufferSize(httpParams,
				BaseCONST.HTTP.BUFFER_SIZE);
		HttpClientParams.setRedirecting(httpParams, true);
		httpParams.setParameter("Connection", "closed");
		httpParams.setParameter(HTTP.USER_AGENT, "lxh_app1_200");
		// String proxyHost = Proxy.getHost(context);
		// int proxyPort = Proxy.getPort(context);
		// boolean isWifiConnected = this.isWifiConnected(context);
		// if (!isWifiConnected && !TextUtils.isEmpty(proxyHost)) {
		// HttpHost proxy = new HttpHost(proxyHost, proxyPort);
		// httpParams.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
		// }
		DefaultHttpClient httpClient = new DefaultHttpClient(httpParams);
		return httpClient;
	}

	private String readStream(InputStream is) {
		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();
		try {
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			return sb.toString();
		} catch (IOException e) {
			log.error("", e);
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					log.error("", e);
				}
			}
		}
		return null;
	}

}
